package com.dd.cloud.user.service.phar.pharservice;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.dd.cloud.user.DTO.CallbackPresStatusReq;
import com.dd.cloud.user.DTO.CancelPresReq;
import com.dd.cloud.user.DTO.CommonParamReq;
import com.dd.cloud.user.DTO.xx.ResultResDTO;
import com.dd.cloud.user.DTO.xx.SendPresBodyDTO;
import com.dd.cloud.user.DTO.xx.SendPresDrugDTO;
import com.dd.cloud.common.constants.PharConstants;
import com.dd.cloud.common.constants.PresConstants;
import com.dd.cloud.user.entity.doctor.DoctorUser;
import com.dd.cloud.user.entity.doctor.PatientMedCard;
import com.dd.cloud.user.entity.order.OrderPay;
import com.dd.cloud.user.entity.phar.Pharmacy;
import com.dd.cloud.user.entity.phar.PharmacyDocking;
import com.dd.cloud.user.entity.pres.PresPrescription;
import com.dd.cloud.user.entity.pres.PresPretrialDrugs;
import com.dd.cloud.user.entity.pres.PresXxDetail;
import com.dd.cloud.user.enums.ExceptionEnum;
import com.dd.cloud.common.interceptor.UserInterceptor;
import com.dd.cloud.user.req.pres.PresCreateReq;
import com.dd.cloud.user.req.pres.PresCreateXxReq;
import com.dd.cloud.user.req.pres.PresPatientAddrReq;
import com.dd.cloud.user.service.doctor.IDoctorUserService;
import com.dd.cloud.user.service.log.ILogErrorService;
import com.dd.cloud.user.service.order.IOrderPayService;
import com.dd.cloud.user.service.phar.IPharmacyDockingService;
import com.dd.cloud.user.service.phar.IPharmacyService;
import com.dd.cloud.user.service.pres.IPresPrescriptionService;
import com.dd.cloud.user.service.pres.IPresPretrialDrugsService;
import com.dd.cloud.user.service.pres.IPresXxDetailService;
import com.dd.cloud.common.vo.LoginInfo;
import com.dd.cloud.common.exception.ZekeException;
import com.dd.cloud.common.utils.BigDecimalUtils;
import com.dd.cloud.common.utils.CalendarUtil;
import com.dd.cloud.common.utils.HttpRequestUtils;
import com.dd.cloud.common.utils.Md5Utils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.IOException;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

/**
 * 康美药房服务类
 *
 * @author Lx
 * @version 1.0
 */
@Slf4j
@Service
public class XxPharService extends PharAbstractService {
    @Autowired
    private IOrderPayService orderPayService;
    @Autowired
    private ILogErrorService logErrorService;
    @Autowired
    private IPresPrescriptionService presPrescriptionService;
    @Autowired
    private IPharmacyService pharmacyService;
    @Autowired
    private IPharmacyDockingService pharmacyDockingService;
    @Autowired
    private IPresPretrialDrugsService presPretrialDrugsService;
    @Autowired
    private IPresXxDetailService presXxDetailService;
    @Autowired
    private IDoctorUserService doctorUserService;

    public static String replace(String s) {
        if (null != s && s.indexOf(".") > 0) {
            //去掉多余的0
            s = s.replaceAll("0+?$", "");
            //如最后一位是.则去掉
            s = s.replaceAll("[.]$", "");
        }
        return s;
    }

    /**
     * 添加药房的处方详情
     *
     * @param req
     * @param medCard
     */
    @Override
    public void addPresDetail(PresCreateReq req, PatientMedCard medCard) {
        LoginInfo loginInfo = UserInterceptor.getLoginUserInfo().get();
        PresCreateXxReq xxReq = (PresCreateXxReq) req;
        PresXxDetail detail = new PresXxDetail();
        BeanUtils.copyProperties(xxReq, detail);
        detail.setTencode(xxReq.getTencode());
        detail.setHospitalName("泽科煎煮");
        detail.setLogisticscost(BigDecimalUtils.divide(BigDecimal.valueOf(xxReq.getExpensesFee()), BigDecimal.valueOf(100)));
        detail.setDiagresult(xxReq.getDisease());
        detail.setDoctorName(loginInfo.getName());
        detail.setName(medCard.getName());
        detail.setGender("男".equals(medCard.getSex()) ? 1 : 2);
        detail.setAge(CalendarUtil.getAge(medCard.getBirthDate()));
        detail.setPhone(medCard.getMobileNumber());
        detail.setCreateDate(LocalDateTime.now());
        DoctorUser du = doctorUserService.getById(loginInfo.getId());
        detail.setDoctorTel(du.getMobileNumber());
        detail.setYizhu(xxReq.getAdvice());
        detail.setTakenum(xxReq.getDoseNum());
        detail.setDose(xxReq.getAllDose());
        detail.setConsultcost(xxReq.getConsultationFee() / 100);
        boolean i = presXxDetailService.save(detail);
        if (!i) {
            throw new ZekeException(ExceptionEnum.PRES_CREATE_ERROR, "处方信息保存失败");
        }
    }

    @Override
    public boolean sendPresToPhar(OrderPay pay) {
        boolean succ = false;
        log.info("发送处方到香雪药房");
        if (StringUtils.isBlank(pay.getServerNo())) {
            //没有处方编码 数据异常, 退款
            orderPayService.refund(pay.getOrderNo(), 0);
            logErrorService.presBackLog("没有处方编码-数据异常, 退款", "处方发送到香雪药房异常", "tencode=" + pay.getServerNo());
            return succ;
        }
        PresPrescription presPrescription = presPrescriptionService.getById(pay.getServerNo());
        if (presPrescription == null) {
            //处方为空, 数据异常, 退款
            orderPayService.refund(pay.getOrderNo(), 0);
            logErrorService.presBackLog("处方为空-数据异常, 退款", "处方发送到香雪药房异常", "tencode=" + pay.getServerNo());
            return succ;
        }
        if (presPrescription.getStatus() == PresConstants.PresStatus.SENDPHARM) {
            //处方已发送到药房, 此为重复回调
            log.info("处方已发送到药房, 此为重复回调");
            return succ;
        }
        PresXxDetail xxDetail = presXxDetailService.getById(pay.getServerNo());
        if (xxDetail == null) {
            orderPayService.refund(pay.getOrderNo(), 0);
            logErrorService.presBackLog("获取发送给药房的详细数据失败, 退款", "处方发送到香雪药房异常", "tencode=" + pay.getServerNo());
            return succ;
        }
        Pharmacy pharmacy = pharmacyService.getById(presPrescription.getPharmId());
        if (pharmacy == null) {
            //药房为空, 数据异常 ,退款
            orderPayService.refund(pay.getOrderNo(), 0);
            logErrorService.presBackLog("药房为空-数据异常, 退款", "处方发送到香雪药房异常", "tencode=" + pay.getServerNo());
            return succ;
        }
        QueryWrapper<PharmacyDocking> qd = new QueryWrapper<>();
        qd.lambda().eq(PharmacyDocking::getPharId, pharmacy.getId())
                .eq(PharmacyDocking::getStatus, PharConstants.DockingStatus.NOMER);
        PharmacyDocking pharmacyDocking = pharmacyDockingService.getOne(qd);
        if (pharmacyDocking == null) {
            //药房为空, 数据异常 ,退款
            orderPayService.refund(pay.getOrderNo(), 0);
            logErrorService.presBackLog("药房对接信息为空-数据异常, 退款", "处方发送到香雪药房异常", "pharId=" + pharmacy.getId());
            return succ;
        }
        SendPresBodyDTO bodyDTO = new SendPresBodyDTO();
        BeanUtils.copyProperties(xxDetail, bodyDTO);
        bodyDTO.setDelnum(pay.getOrderNo());
        bodyDTO.setDeptId(pharmacyDocking.getMchId());
        bodyDTO.setTime(String.valueOf(System.currentTimeMillis()));
        bodyDTO.setSign(Md5Utils.md5Str(pharmacyDocking.getEncryptyKey() + bodyDTO.getDeptId() + bodyDTO.getTime()));
        List<SendPresDrugDTO> drugDTOList = new ArrayList<>();
        QueryWrapper<PresPretrialDrugs> qw = new QueryWrapper<>();
        qw.lambda().eq(PresPretrialDrugs::getTencode, presPrescription.getTencode())
                .eq(PresPretrialDrugs::getStatus, PresConstants.PresDrugsStatus.NOMER);
        List<PresPretrialDrugs> drugsList = presPretrialDrugsService.list(qw);
        if (drugsList == null || drugsList.isEmpty()) {
            //没有处方药品, 数据异常, 退款
            orderPayService.refund(pay.getOrderNo(), 0);
            logErrorService.presBackLog("没有处方药品-数据异常, 退款", "处方发送到香雪药房异常", "tencode=" + pay.getServerNo());
            return succ;
        }
        for (PresPretrialDrugs item : drugsList) {
            SendPresDrugDTO drugDTO = new SendPresDrugDTO();
            drugDTO.setId(item.getDrugId());
            drugDTO.setCode(item.getDrugnum());
            drugDTO.setName(item.getHerbName());
            drugDTO.setUnit(item.getUnit());
            drugDTO.setWeight(BigDecimal.valueOf(item.getDrugallnum()));
            drugDTO.setYgprice(BigDecimalUtils.divide(BigDecimal.valueOf(item.getRetailprice()), BigDecimal.valueOf(100)));
            drugDTO.setSpecialmake(item.getDecocting());
            drugDTOList.add(drugDTO);
        }
        bodyDTO.setDrugList(drugDTOList);
        String result;
        try {
            String bodyJson = JSON.toJSONString(bodyDTO);
            log.info("bodyJson:{}", bodyJson);
            result = HttpRequestUtils.postWithJson(pharmacyDocking.getServicesUrl(), JSON.toJSONString(bodyJson));
            log.info("result:{}", result);
        } catch (IOException e) {
            e.printStackTrace();
            orderPayService.refund(pay.getOrderNo(), 0);
            logErrorService.presBackLog("发送处方失败-数据异常, 退款", "处方发送到香雪药房异常", "tencode=" + pay.getServerNo());
            return succ;
        }
        ResultResDTO resDTO;
        try {
            resDTO = JSON.parseObject(result, ResultResDTO.class);
        } catch (Exception e) {
            orderPayService.refund(pay.getOrderNo(), 0);
            logErrorService.presBackLog("药房返回数据json解析失败, 退款", "处方发送到香雪药房异常", "res=" + result);
            return succ;
        }
        if (!"0".equals(resDTO.getCode())) {
            //接口返回异常 退款
            orderPayService.refund(pay.getOrderNo(), 0);
            logErrorService.presBackLog("药房返回状态码异常, 退款", "处方发送到香雪药房异常", "msg=" + resDTO.getMsg());
            return succ;
        }
        presPrescription.setStatus(PresConstants.PresStatus.SENDPHARM);
        presPrescription.setUpdateDate(LocalDateTime.now());
        boolean flag = presPrescriptionService.updateById(presPrescription);
        if (!flag) {
            logErrorService.presBackLog("发送处方到药房成功, 处方更新失败", "处方发送到香雪药房异常", "jsonBody=" + presPrescription.toString());
        }
        PresXxDetail update = new PresXxDetail();
        update.setTencode(pay.getServerNo());
        ResultResDTO.OrderInfo orderInfo = JSON.parseObject(resDTO.getData(), ResultResDTO.OrderInfo.class);
        update.setOrderNumbr(orderInfo.getOrderNumbr());
        flag = presXxDetailService.updateById(update);
        if (!flag) {
            logErrorService.presBackLog("发送处方到药房成功, 香雪处方详情更新失败", "处方发送到香雪药房异常", "jsonBody=" + presPrescription.toString());
        }
        succ = true;
        return succ;
    }

    @Override
    public void cancelPres(CancelPresReq req) {
    }

    @Override
    public String presCallback(CallbackPresStatusReq req) {
        return "success";
    }

    @Override
    public String expressCallback(CommonParamReq req) {
        return "success";
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updatePresPatientAddrInfo(PresPatientAddrReq req) {
        UpdateWrapper<PresXxDetail> uw = new UpdateWrapper<>();
        uw.lambda().eq(PresXxDetail::getTencode, req.getTencode());
        uw.lambda().set(PresXxDetail::getShrname, req.getReceiver());
        uw.lambda().set(PresXxDetail::getShrtel, req.getMobileNumber());
        uw.lambda().set(PresXxDetail::getAddress, req.getProvince() + req.getCity() + req.getDistrict() + req.getAddr());
        boolean flag = presXxDetailService.update(uw);
        if (!flag) {
            throw new ZekeException(400, "修改处方收货人信息失败");
        }
    }
}
